﻿#pragma once

#include<TopoDS_Shape.hxx>

#include<vtkRenderWindow.h>
#include<vtkRenderer.h>
#include<vtkRenderWindowInteractor.h>
#include<vtkInteractorStyleTrackballCamera.h>
#include<vtkActor.h>
#include<vtkTextActor.h>
#include<vtkPolyDataMapper.h>
#include<vtkButtonWidget.h>
#include<vtkTexturedButtonRepresentation2D.h>
#include<vtkCellPicker.h>
#include<vtkAreaPicker.h>

class VTKRenderer;

/// @brief 自定义交互样式类
class CustomInteractorStyle : public vtkInteractorStyleTrackballCamera 
{
public:
    static CustomInteractorStyle* New();
    vtkTypeMacro(CustomInteractorStyle, vtkInteractorStyleTrackballCamera);

public:
    /// @brief 设置关联的VTKRenderer实例
    /// @param renderer VTK渲染器
    void SetRenderer(VTKRenderer* renderer);

public:
    /// @brief 左键按下
    void OnLeftButtonDown() override;

    /// @brief 左键抬起
    void OnLeftButtonUp() override;

    /// @brief 中键按下
    void OnMiddleButtonDown() override;

    /// @brief 中键抬起
    void OnMiddleButtonUp() override;

    /// @brief 鼠标移动
    void OnMouseMove() override;

private:
    VTKRenderer*    m_Renderer = nullptr;       // 关联的渲染器实例
    bool            m_IsRotating = false;       // 是否正在旋转
    bool            m_IsPanning = false;        // 是否正在平移
    bool            m_IsSelecting = false;      // 是否正在选择（单选/框选）
    bool            m_IsMouseMoveing = false;   // 鼠标是否移动（用于判断是单选还是框选）
    int             m_StartPos[2];              // 框选起始位置
};


/// @brief VTK渲染器
class VTKRenderer
{
public:
    static VTKRenderer& getInstance();

public:
    /// @brief 初始化渲染器
    void Initialize();

    /// @brief 渲染
    /// @param high_API 是否使用高级API渲染
    void Rendering(bool HighAPI = true);

    /// @brief 切换渲染模式
    void SwitchRenderAPI();

    /// @brief 清除场景中的模型
    void ClearAllModels();

public:
    /// @brief 添加模型
    void AddModel(TopoDS_Shape shape);

    /// @brief 移除模型
    void RemoveModel();

public:
    /// @brief 鼠标左键单选
    void HandleSingleSelection(int x, int y);

    /// @brief 鼠标左键框选
    void HandleBoxSelection(int* pos1, int* pos2);

private:
    VTKRenderer();
    ~VTKRenderer();
    VTKRenderer(const VTKRenderer&) = delete;
    VTKRenderer& operator=(const VTKRenderer&) = delete;
    
private:
    /// @brief 更新模型
    /// @param shape 待渲染的OCCT Shape
    /// @param high_API 是否使用高级API渲染
    void UpdateModel();
    
private:
    /// @brief 创建API切换按钮
    void CreateSwitchAPIButton();
    
private:
    /// @brief 初始化鼠标移动
    void InitialMouseEvent();

    /// @brief 更新鼠标位置
    void UpdateMousePosition(int x, int y);    
    
private:
    /// @brief 清除场景中的被选择对象的高亮状态
    void ClearHighLightState();

private:
    // 窗口组件
    vtkNew<vtkRenderWindow>                     m_RenderWindow;         // 渲染窗口
    vtkNew<vtkRenderer>                         m_Renderer;             // 渲染器
    vtkNew<vtkRenderWindowInteractor>           m_Interactor;           // 渲染窗口交互器
    vtkNew<CustomInteractorStyle>               m_InteractorStyle;      // 自定义交互器样式
    vtkNew<vtkCallbackCommand>                  m_RenderCallback;       // 渲染回调函数
    bool                                        m_Isrendering = false;  // 窗口交互器是否已经开始渲染
    
    // 当前模型
    vtkNew<vtkActor>                            m_CurrentActor;
    vtkNew<vtkPolyDataMapper>                   m_CurrentMapper;
    TopoDS_Shape                                m_shape;
    
private:
    // API切换按钮组件
    vtkNew<vtkButtonWidget>                     m_ButtonWidget;
    vtkNew<vtkTexturedButtonRepresentation2D>   m_ButtonRep;
    
    // High/LowAPI切换状态
    bool                                        m_UseHighAPI = true;

private:
    // 鼠标左键单选/框选相关
    vtkNew<vtkTextActor>                        m_MousePositionText;    // 鼠标位置文本
    vtkNew<vtkCellPicker>                       m_CellPicker;           // 单元拾取器
    vtkNew<vtkAreaPicker>                       m_AreaPicker;           // 区域拾取器
    vtkNew<vtkActor>                            m_HighlightedActor;     // 当前高亮Actor
    std::vector<vtkActor*>                      m_SelectedActors;       // 框选Actor集合
    int                                         m_StartPos[2];          // 拖拽起始位置
};